from sqlalchemy.testing import future
from tkhtmlview import HTMLLabel #第三方库的组件，用于在Tkinter显示HTML内容标签组件
import tkinter as tk
from tkinter import ttk,scrolledtext,filedialog
from util.Logger import Logger
import markdown2
from ui.SettingsWindow import SettingsWindow
import asyncio

class MainWindow:
    def __init__(self,root,ai_service,config):
        self.logger=Logger(__name__)
        self.root=root
        self.config=config
        self.ai_service=ai_service
        self.settings_window=SettingsWindow(config)
        try:
            self.logger.info("初始化窗口-----")
            self.setup_ui()
            self.logger.info("主窗口初始化成功！")
        except Exception as e:
            self.logger.critical(f"主窗口初始化失败{str(e)}",exc_info=True)

    def setup_ui(self):
        main_frame=ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH,expand=True,padx=10,pady=10)
        self.editor=scrolledtext.ScrolledText(
            main_frame,
            wrap=tk.WORD,
            font=("宋体",16),
            undo=True,
            maxundo=50,
        )
        self.editor.pack(side=tk.LEFT,fill=tk.BOTH,expand=True)
        self.logger.debug("编辑区域已经初始化！")

        #创建预览区域
        self.preview=HTMLLabel(main_frame)
        self.preview.pack(side=tk.RIGHT,fill=tk.BOTH,expand=True)
        self.logger.debug("预览区域初始化完成！")
        #创建菜单栏
        menubar=tk.Menu(self.root)
        self.root.config(menu=menubar)

        #创建文件菜单及其选项
        file_menu=tk.Menu(menubar,tearoff=0)
        file_menu.add_command(label='打开',command=self.open_file)
        file_menu.add_command(label='保存', command=self.save_file)
        menubar.add_cascade(label='文件',menu=file_menu)
        #创建编辑菜单
        edit_menu=tk.Menu(menubar,tearoff=0)
        edit_menu.add_command(label='撤销',command=lambda:self.editor.event_generate("<<Undo>>"))
        edit_menu.add_command(label='重做',command=lambda:self.editor.event_generate("<<Redo>>"))
        edit_menu.add_command(label='剪切',command=lambda:self.editor.event_generate("<<Cut>>"))
        edit_menu.add_command(label='复制',command=lambda:self.editor.event_generate("<<Copy>>"))
        edit_menu.add_command(label='粘贴',command=lambda:self.editor.event_generate("<<Paste>>"))
        edit_menu.add_command(label='全选',command=lambda:self.editor.tag_add("sel","1.0","end"))
        menubar.add_cascade(label='编辑',menu=edit_menu)
        #创建AI功能菜单
        ai_menu=tk.Menu(menubar,tearoff=0)
        ai_menu.add_command(label="续写",command=self.continue_writing)
        ai_menu.add_command(label="提问",command=self.ask_question)
        ai_menu.add_command(label="扩写",command=self.expand_text)
        ai_menu.add_command(label="文本摘要",command=self.summarize_text)
        ai_menu.add_command(label="文本翻译",command=self.translate_text)
        ai_menu.add_command(label="风格转换",command=self.convert_style)
        ai_menu.add_command(label="代码分析",command=self.analyze_code)

        menubar.add_cascade(label="AI功能",menu=ai_menu)
        settings_menu=tk.Menu(menubar,tearoff=0)
        settings_menu.add_command(label='设置',command=self.show_settings)
        menubar.add_cascade(label='设置',menu=settings_menu)

        self.editor.bind("<KeyRelease>",self.refresh_preview)
        self.root.bind("<Control-o>",lambda e:self.open_file())
        self.root.bind("<Control-s>",lambda e:self.save_file())
        self.root.bind("<Control-z>",lambda e:self.editor.event_generate("<<Undo>>"))
        self.root.bind("<Control-y>", lambda e:self.editor.event_generate("<<Redo>>"))
        self.root.bind("<Control-x>", lambda e: self.editor.event_generate("<<Cut>>"))
        self.root.bind("<Control-c>", lambda e: self.editor.event_generate("<<Copy>>"))
        self.root.bind("<Control-v>", lambda e: self.editor.event_generate("<<Paste>>"))
        self.root.bind("<Control-a>", lambda e: self.editor.tag_add("sel","1.0","end"))
        self.root.bind("<Control-r>",lambda e:self.continue_writing())
        self.root.bind("<Control-q>",lambda e:self.ask_question())
        self.root.bind("<Control-e>",lambda e:self.expand_text())
        self.root.bind("<Control-u>",lambda e:self.summarize_text())
        self.root.bind("<Control-t>",lambda e:self.translate_text())
        self.root.bind("<Control-m>",lambda e:self.convert_style())
        self.root.bind("<Control-n>",lambda e:self.analyze_code())
        file_menu.entryconfig("打开", accelerator="Ctrl+o")
        file_menu.entryconfig("保存", accelerator="Ctrl+s")
        edit_menu.entryconfig("撤销", accelerator="Ctrl+z")
        edit_menu.entryconfig("重做", accelerator="Ctrl+y")
        edit_menu.entryconfig("剪切", accelerator="Ctrl+x")
        edit_menu.entryconfig("复制", accelerator="Ctrl+c")
        edit_menu.entryconfig("粘贴", accelerator="Ctrl+v")
        edit_menu.entryconfig("全选", accelerator="Ctrl+a")
        ai_menu.entryconfig("续写",accelerator="Ctrl+r")
        ai_menu.entryconfig("提问",accelerator="Ctrl+q")
        ai_menu.entryconfig("扩写",accelerator="Ctrl+e")
        ai_menu.entryconfig("文本摘要",accelerator="Ctrl+u")
        ai_menu.entryconfig("文本翻译",accelerator="Ctrl+t")
        ai_menu.entryconfig("风格转换",accelerator="Ctrl+m")
        ai_menu.entryconfig("代码分析",accelerator="Ctrl+n")

    def refresh_preview(self,event:None):
        markdown_str=self.editor.get(1.0,tk.END)
        preview_str=self.get_preview(markdown_str)
        self.preview.set_html(preview_str)

    def get_preview(self,markdown):
        try:
            self.logger.debug("生成预览")
            html=markdown2.markdown(
                markdown,
                extras=['fenced-code-blocks','tables','code-friendly']
            )
            return html
        except Exception as e:
            self.logger.critical(f"预览失败",exc_info=True)
            raise


    def open_file(self):
        file_path=filedialog.askopenfilename(
            filetypes=[("Markdown文件","*.md"),("文本文件","*.txt"),("所有文件","*.*")]
        )
        if file_path:
            try:
                with open(file_path,"r",encoding='utf-8') as f:
                    content=f.read()
                    self.editor.delete(1.0,tk.END)
                    self.editor.insert(tk.END,content)
                    self.logger.info(f"文件{file_path}打开成功")
            except Exception as e:
                self.logger.critical(f"文件{file_path}打开失败",exc_info=True)
                raise

    def save_file(self):
        file_path=filedialog.asksaveasfilename(
            defaultextension=".md",
            filetypes=[("Markdown文件", "*.md"), ("文本文件", "*.txt")]
        )
        if file_path:
            try:
                with open(file_path,"w",encoding='utf-8') as f:
                    content=self.editor.get(1.0,tk.END)
                    f.write(content)
                    self.logger.info(f"文件{file_path}保存成功")
            except Exception as e:
                self.logger.critical(f"文件{file_path}保存失败{str(e)}",exc_info=True)
                raise

    def show_settings(self):
        self.logger.info("显示设置窗口")
        try:
            self.settings_window.show(self.root)
            self.logger.info("设置窗口显示成功")
        except :
            self.logger.info("设置窗口显示错误")

    def continue_writing(self):
        self.logger.info("续写")
        try:
            text=self.editor.get(tk.SEL_FIRST,tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择续写文本")
            return

        def callback(future):     #回调函数是一种在异步编程和事件驱动编程中广泛使用的技术，它是指在某个操作完成或某个事件发生时被调用的函数。回调函数允许程序在等待某个耗时操作时不阻塞主线程，而是在操作完成后自动执行预先定义好的函数来处理结果。
            try:
                continuation=future.result()
                if continuation:
                    self.editor.replace(tk.SEL_FIRST,tk.SEL_LAST,continuation)
                    self.logger.info("续写成功")
            except Exception as e:
                self.logger.critical(f"续写失败{str(e)}",exc_info=True)

        future=asyncio.run_coroutine_threadsafe(
            self.ai_service.continue_writing(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)

    def ask_question(self):
        self.logger.info("提问")
        try:
            question=self.editor.get(tk.SEL_FIRST,tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择提问内容")
            return

        def callback(future):
            try:
                answer=future.result()
                if answer:
                    self.show_analysis_result(answer)
                    self.logger.info("回答成功")
            except Exception as e:
                self.logger.critical(f"回答失败{str(e)}",exc_info=True)

        future=asyncio.run_coroutine_threadsafe(
            self.ai_service.ask_question(question),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)

    def expand_text(self):
        """扩写内容"""
        self.logger.info("扩写")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择扩写文本")
            return

        def callback(future):
            try:
                continuation = future.result()
                if continuation:
                    self.editor.replace(tk.SEL_FIRST,tk.SEL_LAST, continuation)
                    self.logger.info("扩写成功")
            except Exception as e:
                self.logger.critical(f"扩写失败{str(e)}", exc_info=True)

        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.expand_text(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)

    def show_analysis_result(self,analysis):
        try:
            self.logger.info("问题答案：")
            #创建独立显示的窗口
            result_window=tk.Toplevel(self.root)
            result_window.title("问题结果")
            result_text=scrolledtext.ScrolledText(result_window,wrap=tk.WORD)
            result_text.pack(fill=tk.BOTH,expand=True)
            result_text.insert(tk.END,str(analysis))
            self.logger.debug("展示分析结果成功")
        except Exception as e:
            self.logger.debug(f"展示分析结果失败{str(e)}",exc_info=True)

    def summarize_text(self):
        self.logger.info("初始化文本摘要")
        try:
            text=self.editor.get(tk.SEL_FIRST,tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择摘要文本")
            return
        def callback(future):
            try:
                summary=future.result()
                if summary:
                    self.show_analysis_result(summary)
                    self.logger.info("摘要成功")
            except Exception as e:
                self.logger.critical(f"摘要失败{str(e)}", exc_info=True)

        future=asyncio.run_coroutine_threadsafe(
            self.ai_service.summarize_text(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)

    def translate_text(self):
        self.logger.info("初始化文本翻译")
        try:
            text=self.editor.get(tk.SEL_FIRST,tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择翻译文本")
            return
        translation_window=tk.Toplevel(self.root)
        translation_window.title("翻译选项")
        ttk.Label(translation_window,text="目标语言").grid(row=0,column=0,padx=5,pady=5)
        self.target_language_var=tk.StringVar(value="英语(English)")
        language_options={
            "en":"英语(English)",
            "zh":"中文(Chinese)",
            "jp":"日语(Japanese)",
            "fr":"法语(French)",
            "de":"德语(German)",
            "es":"西班牙语(Spanish)",
        }
        language_combobox=ttk.Combobox(
            translation_window,
            textvariable=self.target_language_var,
            values=list(language_options.values()),
            state="readonly"
        )
        language_combobox.grid(row=0,column=1,padx=5,pady=5)

        def callback(future):
            try:
                summary=future.result()
                if summary:
                    self.show_analysis_result(summary)
                    self.logger.info("翻译成功")
            except Exception as e:
                self.logger.critical(f"翻译失败{str(e)}", exc_info=True)

        def start_translation():
            translation_window.destroy()
            selected_language=self.target_language_var.get()
            target_language={v:k for k,v in language_options.items()}[selected_language]
            future = asyncio.run_coroutine_threadsafe(
                self.ai_service.translate_text(text,target_language),
                asyncio.get_event_loop()
            )
            future.add_done_callback(callback)
        ttk.Button(translation_window,text="开始翻译",command=start_translation).grid(row=1,column=0,columnspan=2,pady=5)

    def convert_style(self):
        self.logger.info("初始化风格转换")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择转换文本")
            return
        conversation_window = tk.Toplevel(self.root)
        conversation_window.title("风格选项")
        ttk.Label(conversation_window, text="风格").grid(row=0, column=0, padx=5, pady=5)
        self.target_style_var = tk.StringVar(value="informal")
        style_options = {
            "formal": "正式风格",
            "casual": "口语风格",
            "professional": "专业技术",
            "literary": "文学风格",
            "business": "商务风格",
            "humorous": "幽默风格",
        }
        style_combobox = ttk.Combobox(
            conversation_window,
            textvariable=self.target_style_var,
            values=list(style_options.values()),
            state="readonly"
        )
        style_combobox.grid(row=0, column=1, padx=5, pady=5)

        def callback(future):
            try:
                summary = future.result()
                if summary:
                    self.show_analysis_result(summary)
                    self.logger.info("转换成功")
            except Exception as e:
                self.logger.critical(f"转换失败{str(e)}", exc_info=True)

        def start_conversation():
            conversation_window.destroy()
            selected_style = self.target_style_var.get()
            target_style = {v: k for k, v in style_options.items()}[selected_style]
            future = asyncio.run_coroutine_threadsafe(
                self.ai_service.convert_style(text, target_style),
                asyncio.get_event_loop()
            )
            future.add_done_callback(callback)

        ttk.Button(conversation_window, text="开始转换", command=start_conversation).grid(row=1, column=0, columnspan=2,pady=5)

    def analyze_code(self):
        self.logger.info("初始化代码分析")
        try:
            text = self.editor.get(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            self.logger.warning("未选择分析代码")
            return

        def callback(future):
            try:
                code = future.result()
                if code:
                    self.show_analysis_result(code)
                    self.logger.info("分析成功")
            except Exception as e:
                self.logger.critical(f"分析失败{str(e)}", exc_info=True)

        future = asyncio.run_coroutine_threadsafe(
            self.ai_service.analyze_code(text),
            asyncio.get_event_loop()
        )
        future.add_done_callback(callback)